﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.BizTalk.Component.Interop;
using System.Reflection;
using System.Globalization;
using System.Xml;
using log4net;
using AppFx.BizTalk.Diagnostics;

namespace AppFx.BizTalk.PipelineComponents
{
    /// <summary>
    /// Assigns a BTS.Operation value based on mappings from the message type
    /// </summary>
    /// <remarks>
    /// The mappings look something like:
    /// <BtsOperationMapping>
	/// <MessageType Name="1" BTSOperation="a"/>
	/// <MessageType Name="2" BTSOperation="b"/>
    /// </BtsOperationMapping>
    /// </remarks>
    [ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
    [ComponentCategory(CategoryTypes.CATID_Any)]    
    [System.Runtime.InteropServices.Guid(ComponentGuid)]
    public class BTSOperationMapping : BaseCustomPipelineComponent, IComponent, IComponentUI, IPersistPropertyBag
    {
        private static readonly ILog Log = LogFactory.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public const string ComponentGuid = "4D2DF7C9-EE10-4BB9-B9DD-F1CFEC764D6C";
        public const string ComponentDescription = "Assigns a BTS.Operation based on the BTS.MessageType";
        public  const string ComponentName = "BTS Operation Mapping";

        private string _Mappings = string.Empty;
                        
        #region Properties
        /// <summary>
        /// Soap Action Property
        /// </summary>
        public string Mappings
        {
            get { return _Mappings; }
            set { _Mappings = value; }
        }
        #endregion

         public BTSOperationMapping()
            : base(ComponentName, typeof(BTSOperationMapping), ComponentDescription)
        {
            
        }

        #region IComponent Members
        /// <summary>
        /// Processing of the component
        /// </summary>
        /// <param name="pContext"></param>
        /// <param name="pInMsg"></param>
        /// <returns></returns>
        public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(IPipelineContext pContext, Microsoft.BizTalk.Message.Interop.IBaseMessage pInMsg)
        {
            if (pInMsg == null)
                throw new ArgumentNullException("pInMsg");

            string messageType = base.ReadContextPropertyAsString(pInMsg.Context, new BTS.MessageType());
            base.WriteContextProperty(pInMsg.Context, new BTS.Operation(), messageType);
            if (!string.IsNullOrEmpty(this._Mappings))
            {
                string operation = GetOperation(messageType);
                if(!string.IsNullOrEmpty(operation))
                    base.WriteContextProperty(pInMsg.Context, new BTS.Operation(), operation);
            }
               
            return pInMsg;
        }
        #endregion

        #region IComponentUI Members
        /// <summary>
        /// Icon
        /// </summary>
        public IntPtr Icon
        {
            get { return IntPtr.Zero; }
        }
        /// <summary>
        /// Validate
        /// </summary>
        /// <param name="projectSystem"></param>
        /// <returns></returns>
        public System.Collections.IEnumerator Validate(object projectSystem)
        {
            return null;
        }
        #endregion

        #region IPersistPropertyBag Members
        /// <summary>
        /// The guid
        /// </summary>
        /// <param name="classID"></param>
        public void GetClassID(out Guid classID)
        {
            classID = new Guid(ComponentGuid);
        }
        /// <summary>
        /// No implementation
        /// </summary>
        public void InitNew()
        {
        }
        /// <summary>
        /// Loads from property bag
        /// </summary>
        /// <param name="propertyBag"></param>
        /// <param name="errorLog"></param>        
        public void Load(IPropertyBag propertyBag, int errorLog)
        {
            try
            {
                base.ReadPropertyBag(propertyBag, "Mappings", ref this._Mappings);
            }
            catch (Exception ex)
            {
                string message = string.Format(CultureInfo.InvariantCulture, "IPersistPropertyBag.Load error: {0}", ex.ToString());
                Log.Error(message, ex);
                throw;
            }
        }
        /// <summary>
        /// Sdaves state to property bag
        /// </summary>
        /// <param name="propertyBag"></param>
        /// <param name="clearDirty"></param>
        /// <param name="saveAllProperties"></param>
        public void Save(IPropertyBag propertyBag, bool clearDirty, bool saveAllProperties)
        {
            try
            {
                base.WritePropertyBag(propertyBag, "Mappings", this._Mappings);
            }
            catch (Exception ex)
            {
                string message = string.Format(CultureInfo.InvariantCulture, "IPersistPropertyBag.Load error: {0}", ex.ToString());
                Log.Error(message, ex);
                throw;
            }
        }
        #endregion

        public string GetOperation(string messageType)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(this._Mappings);
            XmlNodeList nodes = xmlDoc.SelectNodes("/BtsOperationMapping/MessageType");
            foreach (XmlNode node in nodes)
            {
                if (node.Attributes["Name"] != null && node.Attributes["BTSOperation"] != null)
                {
                    if (node.Attributes["Name"].Value == messageType)
                    {
                        return node.Attributes["BTSOperation"].Value;
                    }
                }
            }
            return null;
        }
    }
}



